package com.helin.helinhealth.service;


import com.baomidou.mybatisplus.extension.service.IService;
import com.helin.helinhealth.entity.Medicine;

import java.util.List;

/**
 * 药品服务接口
 * 
 * <p>
 * 该接口定义了药品管理相关的业务逻辑操作，包括药品的增删改查、
 * 药品服用状态管理、库存管理等功能。继承自MyBatis-Plus的IService接口，
 * 拥有基础的CRUD能力，并在此基础上扩展了特定业务需求的方法。
 * </p>
 * 
 * <p>
 * 主要功能包括：
 * - 药品信息的保存和更新
 * - 获取用户的药品列表
 * - 获取今日待服用药品
 * - 药品库存管理和预警
 * - 服药打卡功能
 * </p>
 */
public interface MedicineService extends IService<Medicine> {

    /**
     * 添加或更新药品信息
     * 
     * <p>
     * 根据药品ID是否存在，自动判断是新增还是更新操作。
     * 新增时会自动关联当前登录用户，更新时会进行权限验证，
     * 确保用户只能修改自己的药品信息。
     * </p>
     * 
     * @param medicine 药品信息对象
     * @throws RuntimeException 当权限验证失败或操作异常时抛出
     */
    void saveOrupdate(Medicine medicine);
    
    /**
     * 获取指定用户的药品列表
     * 
     * <p>
     * 查询指定用户的所有有效药品，按创建时间降序排序。
     * 主要用于药品管理页面的数据展示。
     * </p>
     * 
     * @param userId 用户ID (openid)
     * @return 药品列表
     */
    List<Medicine> getUserMedicineList(String userId);
    
    /**
     * 获取当前登录用户今日需服用的药品
     * 
     * <p>
     * 查询当前用户今日尚未服用的药品，按服药时间升序排序。
     * 用于实现首页的服药提醒功能。
     * </p>
     * 
     * @return 今日待服用的药品列表
     */
    List<Medicine> getCurrentUserTodayMedicines();
    
    /**
     * 获取库存低于指定阈值的药品
     * 
     * <p>
     * 查询当前用户库存天数不足的药品，用于药品库存预警功能。
     * 按库存天数升序排序，库存越少的药品排在越前面。
     * </p>
     * 
     * @param threshold 库存阈值（天数）
     * @return 库存低的药品列表
     */
    List<Medicine> getLowStockMedicines(Integer threshold);
    
    /**
     * 更新药品服用状态
     * 
     * <p>
     * 更新指定药品的服用状态，用于实现服药打卡功能。
     * 使用乐观锁机制防止并发更新问题，会进行权限验证，
     * 确保用户只能更新自己的药品状态。
     * </p>
     * 
     * @param id 药品ID
     * @param isTaken 是否已服用
     * @return 更新是否成功
     */
    boolean updateMedicineTakenStatus(Long id, Boolean isTaken);
    
    /**
     * 减少药品库存天数
     * 
     * <p>
     * 减少指定药品的库存天数，用于记录用户服药后的库存变化。
     * 会确保库存天数不为负数，并在库存不足时进行预警。
     * 使用乐观锁机制防止并发更新问题。
     * </p>
     * 
     * @param id 药品ID
     * @param days 减少的天数
     * @return 更新是否成功
     */
    boolean reduceStockDays(Long id, Integer days);
}